package com.tedu.api.map;

import org.junit.Test;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.function.BiConsumer;

/**
 * java.util
 * Map与Collection同等级的顶级接口
 * Map映射接口
 * 作用:一个元素由两个对象构成,分别为Key(键)和Value(值)构成
 * 获取数据:采用键取值,通常与数据搭配,获取字段下的值
 * 特点:无序、无下标、键不可以重复【唯一性】、值可以重复
 * <p>
 * Map接口---实例化【创建】对象---
 * Hashmap哈希卖破[超🐓常用]:存储性能快，由哈希算法底层实现，键可以存null，
 * 但只允许一个，主要通过键找值
 * LinkedHashMap[不常用]:方法与HashMap,用于日志记录按照时间顺序
 * TreeMap[old不用，你气不气]:性能 插入删除贼勾八慢，线程又多又不安全，还他娘占用内存
 *  *                       【算法:红黑树实现--需要进行树的旋转和调整以保持平衡】
 * Hashtable[old不用]:jdk1.0，性能 插入删除更是贼勾八慢，线程也是又多又不安全，也他娘占用内存
 *                       【算法:红黑树实现--需要进行树的旋转和调整以保持平衡】
 * Hashtable----被ConcurrentHashMap取代
 * ConcurrentHashMap[较为常用]映射集合接口:跟线程在一块用，学习多线程
 *
 * 重点:Map接口中方法【Map接口方法与HashMap方法类似  90%】
 *
 * 12个集合类【不同集合的不同保存状态】---都是保存数据的--增删改查  写--看懂
 */
public class MapAPI {
    @Test
    public void testMap() {
        //创建Map映射接口---多态
        Map<Object/*键*/, String/*值*/> map = new HashMap<>();
        //键--->值  添加元素:  K-V
        /**
         * put("键","值")  返回值:V  value 值
         * 作用：存键值对形态一组数据
         */
        map.put("祖安怒兽", "沃里克");//存一个键和一个值
        map.put("时间刺客", "艾克");
        map.put("祖安花火", "泽丽");
        map.put("暴走萝莉", "金克丝");
        System.out.println("祖安map映射存储数据：" + map);
        /**
         * get(E e) 根据键来找到对应的值  返回值:V value
         * remove(K Key) 通过Key删除一组数值对
         * size()=获取map的元素总数  返回值:int
         */
        //找到map集合中 金克丝的值
        String jinkesi = map.get("暴走萝莉");//前缀String去找
        System.out.println("爆爆是：" + jinkesi);
        //get()  键不存在则返回默认值:基本类型、引用类型:null值
        map.remove("祖安花火");
        System.out.println(map);
        System.out.println("获取map元素总数:" + map.size());
        /**
         * containsKey()
         * 作用:判断map中元素"对象:键 "是否存在
         * containsValue()
         * 作用:判断map中元素"对象:值 "是否存在
         */
        boolean bk = map.containsKey("时间刺客");//boolean类型的返回值
        System.out.println("map元素：键" + bk);
        boolean bv = map.containsValue("艾克");
        System.out.println("map元素：值" + bv);
    }

    /**
     * map元素遍历  键唯一性-->值 都是Set集合
     * keySet() 获取map元素中所有的键
     * values() 获取map元素中所有的值
     * entrySet() 获取map元素中所有的键和值
     */
    @Test
    public void testKve() {
        //创建Map映射集合
        Map<Object, String> map = new HashMap<>();
        map.put("影哨", "阿克尚");
        map.put("破败之王", "佛耶戈");
        map.put("灵罗娃娃", "格温");
        map.put("魂锁典狱长", "锤石");
        //1.获取map集合元素中 键 数据 keySet()
        Set<Object> sets = map.keySet();
        //1.?  遍历从map元素中获取的键--数据   泛型统一类型刚好适合增强for
        for (Object/*神魔类型用什么,这个是Object*/ keys : sets) {
            System.out.println("输出map元素中：" + keys);
        }
        //2.获取map集合元素中 值 数据  values() 返回值:Collection
        Collection<String> cs = map.values();
        //2.2遍历从map元素中获取的值--数据
        for (String values : cs) {
            System.out.println(cs);
        }
        //3.获取map集合元素[entrySet]中数据:键和值  entrySet()返回值:Set<Map.Entry<K,V>>
        //Map.Entry<K,V> 保存map元素一组数据,表示:一组entry
        //Entry是一个内部接口 保存Map中所有组数据  使用Map.Entry
        Set<Map.Entry<Object, String/*类型*/>> entrys = map.entrySet();
        //获取map映射集合所有元素【entry】
        //3.1遍历map所有的键和值【所有entry/元素/数据--成对】
        for(Map.Entry<Object,String> entry:entrys) {//用上面<>内所有的东西外加一个新的命名
            System.out.println(entrys);
            //3.2获取键
            Object keys=entry.getKey();
            //3.3获取值
            String values=entry.getValue();
            //3.4打印
            System.out.println(keys+"只因"+values);
        }
    }

    /**
     * forEach   遍历map中所有对元素/entry
     * for+entrySet()集合 = forEach()
     * BiConsumer是个接口参数 传入
     * 针对map存储问题--封装接口--提供方法:accept()  帮你拿到一对数据  所有entry
     */
    @Test
    public void testForEach(){
        Map<Object, String> map = new HashMap<>();
        map.put("法外狂徒", "格雷福斯");
        map.put("卡牌大师", "崔斯特");
        map.put("赏金猎人", "厄运小姐(莎拉)");
        map.put("不羁之悦", "尼菈");
        //Map映射集合--提供一套方法:forEach()
        map.forEach(new BiConsumer<Object, String>() {
            //accept(K,V) 方法:获取到Entry中---每组entry
            //K--键  V--值
            public void accept(Object key, String value) {
                System.out.println(key+"欸嘿"+value);

            }
        });

    }

    /**
     * HashMap 映射集合
     * HashMap基本与Map方法一致
     * putIfAbsent()作用：用来给HashMap映射集合存入【Entry/一组数据:一组键值】
     *                   如果存入一组数据,不存在的键,插入HashMap
     *                   存在的键,不插入HashMap
     *       哈希算法--唯一性
     */
    @Test
    public void testHashMap(){
        //创建Map映射集合
        Map<Object, String> map = new HashMap<>();
        map.put("冰霜女巫", "丽桑卓");
        map.put("不灭狂雷", "沃利贝尔");
        map.put("山隐之焰", "奥恩");
        map.put("冰晶凤凰", "艾尼维亚");
        System.out.println("弗雷尔卓德HashMap存值:"+map);

    }
}
